//--------------------------------------------------------------
//
// Size evaluation functions. Based on David Adams paper.
//
//              Author : ripertl
// 
//--------------------------------------------------------------
#include <igraph.h>
#include <assert.h>
#include "../global.h"

//#define DEBUG

// GetSize
float getSize(igraph_t graph, igraph_integer_t node){
  // This just returns the value of the "size" attribute which has to be set 
  // during dungeon generation.

  roominfo *ri;
  ri = get_roominfo(&graph, node);

  return (float) sqrtf((ri->w)*(ri->h));

}

// SizeEvaluator1
float sizeevaluator1(igraph_t graph){
  // The size of the dungeon is estimated by the number of rooms (i.e. nodes)
  return (float) igraph_vcount(&graph);

}

// SizeEvaluator2
float sizeevaluator2(igraph_t graph){
  
  float size = 0;

  igraph_vit_t iterator;
  igraph_vs_t vs;
  igraph_vs_all(&vs);

  // iterator creation to explore all the nodes.
  igraph_vit_create(&graph, vs, &iterator);

  while (!IGRAPH_VIT_END(iterator)) {
    // Here is the cumulative suface of the rooms.
    size += getSize(graph,IGRAPH_VIT_GET(iterator));
    IGRAPH_VIT_NEXT(iterator);
  }

  return size;
}


// SizeEvaluator3
float sizeevaluator3(igraph_t graph){

  unsigned int connectivity = 0;
  float size = 0;

  igraph_vector_t res;
  igraph_vit_t iterator;
  igraph_vs_t vsall;
  igraph_vs_t vs;

  igraph_vector_init(&res,4);

  igraph_vs_all(&vsall);

  igraph_vit_create(&graph, vsall, &iterator);

  while(!IGRAPH_VIT_END(iterator)){

    igraph_vs_1(&vs,IGRAPH_VIT_GET(iterator));

    igraph_neighborhood_size(&graph, &res, vs, 1, IGRAPH_ALL); 
    int N = igraph_vector_e(&res,0) - 1;
    
#ifdef DEBUG
    printf(" Noeud %d : %d voisins \n",(int) IGRAPH_VIT_GET(iterator),N);
#endif

    connectivity += (N==1?1:N-1);

    IGRAPH_VIT_NEXT(iterator);
  }

  // the size is the average number of neighbors
  size = ((float) connectivity) / ((float) igraph_vcount(&graph));

  igraph_vector_destroy(&res);
  return size;

}

// SizeEvaluator4

float sizeevaluator4(igraph_t *graph, int start, igraph_vector_t *end, igraph_vector_t *weights){

  float path_size = 0;
  float size = 0;
  
  igraph_vector_ptr_t res;
  igraph_vit_t iterator;
  igraph_vs_t vsend;

  igraph_vs_t vs;

  int nbexits = igraph_vector_size(end);
  int i = 0;

#ifdef DEBUG
  printf("nbexits : %d\n",nbexits);
#endif
  
  // res initialisation
  igraph_vector_ptr_init(&res, nbexits);
  
  for(i=0;i<nbexits;i++){
    igraph_vector_t path;
    igraph_vector_init(&path,1);
    igraph_vector_ptr_set(&res,i,&path);

  }

#ifdef DEBUG
  printf("res size : %d\n", igraph_vector_ptr_size(&res));
#endif

  igraph_vs_vector(&vsend,end);
  igraph_get_shortest_paths_dijkstra(graph, &res, start, vsend, weights, IGRAPH_ALL);

  // create a vertex set associated with the vector.

  for(i=0; i<nbexits; i++){
    igraph_vs_vector(&vs, igraph_vector_ptr_e(&res,i));
    igraph_vit_create(graph, vs, &iterator);
    while(!IGRAPH_VIT_END(iterator)){

      path_size += getSize(*graph,IGRAPH_VIT_GET(iterator));
      
#ifdef DEBUG
      printf(" Noeud %d \n",(int) IGRAPH_VIT_GET(iterator));
#endif
      
      IGRAPH_VIT_NEXT(iterator);
      
    }
    igraph_vit_destroy(&iterator);
  }

   // Here is computed the average surface explored by a player

   path_size = path_size/nbexits;
   size = path_size/sizeevaluator2(*graph);

   igraph_vs_destroy(&vsend);
   igraph_vs_destroy(&vs);
   igraph_vector_ptr_destroy(&res);
   return size;

}


